home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Textures SDK / common / bspfile.c next >
C/C++ Source or Header  |  1998-12-02  |  17KB  |  710 lines

  1. /***
  2. *
  3. *    Copyright (c) 1998, Valve LLC. All rights reserved.
  4. *    
  5. *    This product contains software technology licensed from Id 
  6. *    Software, Inc. ("Id Technology").  Id Technology (c) 1996 Id Software, Inc. 
  7. *    All Rights Reserved.
  8. *
  9. ****/
  10.  
  11. #include "cmdlib.h"
  12. #include "mathlib.h"
  13. #include "bspfile.h"
  14. #include "scriplib.h"
  15.  
  16. //=============================================================================
  17.  
  18. int            nummodels;
  19. dmodel_t    dmodels[MAX_MAP_MODELS];
  20. int            dmodels_checksum;
  21.  
  22. int            visdatasize;
  23. byte        dvisdata[MAX_MAP_VISIBILITY];
  24. int            dvisdata_checksum;
  25.  
  26. int            lightdatasize;
  27. byte        dlightdata[MAX_MAP_LIGHTING];
  28. int            dlightdata_checksum;
  29.  
  30. int            texdatasize;
  31. byte        dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
  32. int            dtexdata_checksum;
  33.  
  34. int            entdatasize;
  35. char        dentdata[MAX_MAP_ENTSTRING];
  36. int            dentdata_checksum;
  37.  
  38. int            numleafs;
  39. dleaf_t        dleafs[MAX_MAP_LEAFS];
  40. int            dleafs_checksum;
  41.  
  42. int            numplanes;
  43. dplane_t    dplanes[MAX_MAP_PLANES];
  44. int            dplanes_checksum;
  45.  
  46. int            numvertexes;
  47. dvertex_t    dvertexes[MAX_MAP_VERTS];
  48. int            dvertexes_checksum;
  49.  
  50. int            numnodes;
  51. dnode_t        dnodes[MAX_MAP_NODES];
  52. int            dnodes_checksum;
  53.  
  54. int            numtexinfo;
  55. texinfo_t    texinfo[MAX_MAP_TEXINFO];
  56. int            texinfo_checksum;
  57.  
  58. int            numfaces;
  59. dface_t        dfaces[MAX_MAP_FACES];
  60. int            dfaces_checksum;
  61.  
  62. int            numclipnodes;
  63. dclipnode_t    dclipnodes[MAX_MAP_CLIPNODES];
  64. int            dclipnodes_checksum;
  65.  
  66. int            numedges;
  67. dedge_t        dedges[MAX_MAP_EDGES];
  68. int            dedges_checksum;
  69.  
  70. int            nummarksurfaces;
  71. unsigned short        dmarksurfaces[MAX_MAP_MARKSURFACES];
  72. int            dmarksurfaces_checksum;
  73.  
  74. int            numsurfedges;
  75. int            dsurfedges[MAX_MAP_SURFEDGES];
  76. int            dsurfedges_checksum;
  77.  
  78. int            num_entities;
  79. entity_t    entities[MAX_MAP_ENTITIES];
  80.  
  81. /*
  82. ===============
  83. FastChecksum
  84. ===============
  85. */
  86.  
  87. int FastChecksum(void *buffer, int bytes)
  88. {
  89.     int    checksum = 0;
  90.  
  91.     while( bytes-- )  
  92.         checksum = _rotl(checksum, 4) ^ *((char *)buffer)++;
  93.  
  94.     return checksum;
  95. }
  96.  
  97. /*
  98. ===============
  99. CompressVis
  100. ===============
  101. */
  102. int CompressVis (byte *vis, byte *dest)
  103. {
  104.     int        j;
  105.     int        rep;
  106.     int        visrow;
  107.     byte    *dest_p;
  108.     
  109.     dest_p = dest;
  110.     visrow = (numleafs + 7)>>3;
  111.     
  112.     for (j=0 ; j<visrow ; j++)
  113.     {
  114.         *dest_p++ = vis[j];
  115.         if (vis[j])
  116.             continue;
  117.  
  118.         rep = 1;
  119.         for ( j++; j<visrow ; j++)
  120.             if (vis[j] || rep == 255)
  121.                 break;
  122.             else
  123.                 rep++;
  124.         *dest_p++ = rep;
  125.         j--;
  126.     }
  127.     
  128.     return dest_p - dest;
  129. }
  130.  
  131.  
  132. /*
  133. ===================
  134. DecompressVis
  135. ===================
  136. */
  137. void DecompressVis (byte *in, byte *decompressed)
  138. {
  139.     int        c;
  140.     byte    *out;
  141.     int        row;
  142.  
  143.     row = (numleafs+7)>>3;    
  144.     out = decompressed;
  145.  
  146.     do
  147.     {
  148.         if (*in)
  149.         {
  150.             *out++ = *in++;
  151.             continue;
  152.         }
  153.     
  154.         c = in[1];
  155.         in += 2;
  156.         while (c)
  157.         {
  158.             *out++ = 0;
  159.             c--;
  160.         }
  161.     } while (out - decompressed < row);
  162. }
  163.  
  164. //=============================================================================
  165.  
  166. /*
  167. =============
  168. SwapBSPFile
  169.  
  170. Byte swaps all data in a bsp file.
  171. =============
  172. */
  173. void SwapBSPFile (qboolean todisk)
  174. {
  175.     int                i, j, c;
  176.     dmodel_t        *d;
  177.     dmiptexlump_t    *mtl;
  178.  
  179.     
  180. // models    
  181.     for (i=0 ; i<nummodels ; i++)
  182.     {
  183.         d = &dmodels[i];
  184.  
  185.         for (j=0 ; j<MAX_MAP_HULLS ; j++)
  186.             d->headnode[j] = LittleLong (d->headnode[j]);
  187.  
  188.         d->visleafs = LittleLong (d->visleafs);
  189.         d->firstface = LittleLong (d->firstface);
  190.         d->numfaces = LittleLong (d->numfaces);
  191.         
  192.         for (j=0 ; j<3 ; j++)
  193.         {
  194.             d->mins[j] = LittleFloat(d->mins[j]);
  195.             d->maxs[j] = LittleFloat(d->maxs[j]);
  196.             d->origin[j] = LittleFloat(d->origin[j]);
  197.         }
  198.     }
  199.  
  200. //
  201. // vertexes
  202. //
  203.     for (i=0 ; i<numvertexes ; i++)
  204.     {
  205.         for (j=0 ; j<3 ; j++)
  206.             dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
  207.     }
  208.         
  209. //
  210. // planes
  211. //    
  212.     for (i=0 ; i<numplanes ; i++)
  213.     {
  214.         for (j=0 ; j<3 ; j++)
  215.             dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
  216.         dplanes[i].dist = LittleFloat (dplanes[i].dist);
  217.         dplanes[i].type = LittleLong (dplanes[i].type);
  218.     }
  219.     
  220. //
  221. // texinfos
  222. //    
  223.     for (i=0 ; i<numtexinfo ; i++)
  224.     {
  225.         for (j=0 ; j<8 ; j++)
  226.             texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
  227.         texinfo[i].miptex = LittleLong (texinfo[i].miptex);
  228.         texinfo[i].flags = LittleLong (texinfo[i].flags);
  229.     }
  230.     
  231. //
  232. // faces
  233. //
  234.     for (i=0 ; i<numfaces ; i++)
  235.     {
  236.         dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
  237.         dfaces[i].planenum = LittleShort (dfaces[i].planenum);
  238.         dfaces[i].side = LittleShort (dfaces[i].side);
  239.         dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
  240.         dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
  241.         dfaces[i].numedges = LittleShort (dfaces[i].numedges);
  242.     }
  243.  
  244. //
  245. // nodes
  246. //
  247.     for (i=0 ; i<numnodes ; i++)
  248.     {
  249.         dnodes[i].planenum = LittleLong (dnodes[i].planenum);
  250.         for (j=0 ; j<3 ; j++)
  251.         {
  252.             dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
  253.             dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
  254.         }
  255.         dnodes[i].children[0] = LittleShort (dnodes[i].children[0]);
  256.         dnodes[i].children[1] = LittleShort (dnodes[i].children[1]);
  257.         dnodes[i].firstface = LittleShort (dnodes[i].firstface);
  258.         dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
  259.     }
  260.  
  261. //
  262. // leafs
  263. //
  264.     for (i=0 ; i<numleafs ; i++)
  265.     {
  266.         dleafs[i].contents = LittleLong (dleafs[i].contents);
  267.         for (j=0 ; j<3 ; j++)
  268.         {
  269.             dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
  270.             dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
  271.         }
  272.  
  273.         dleafs[i].firstmarksurface = LittleShort (dleafs[i].firstmarksurface);
  274.         dleafs[i].nummarksurfaces = LittleShort (dleafs[i].nummarksurfaces);
  275.         dleafs[i].visofs = LittleLong (dleafs[i].visofs);
  276.     }
  277.  
  278. //
  279. // clipnodes
  280. //
  281.     for (i=0 ; i<numclipnodes ; i++)
  282.     {
  283.         dclipnodes[i].planenum = LittleLong (dclipnodes[i].planenum);
  284.         dclipnodes[i].children[0] = LittleShort (dclipnodes[i].children[0]);
  285.         dclipnodes[i].children[1] = LittleShort (dclipnodes[i].children[1]);
  286.     }
  287.  
  288. //
  289. // miptex
  290. //
  291.     if (texdatasize)
  292.     {
  293.         mtl = (dmiptexlump_t *)dtexdata;
  294.         if (todisk)
  295.             c = mtl->nummiptex;
  296.         else
  297.             c = LittleLong(mtl->nummiptex);
  298.         mtl->nummiptex = LittleLong (mtl->nummiptex);
  299.         for (i=0 ; i<c ; i++)
  300.             mtl->dataofs[i] = LittleLong(mtl->dataofs[i]);
  301.     }
  302.     
  303. //
  304. // marksurfaces
  305. //
  306.     for (i=0 ; i<nummarksurfaces ; i++)
  307.         dmarksurfaces[i] = LittleShort (dmarksurfaces[i]);
  308.  
  309. //
  310. // surfedges
  311. //
  312.     for (i=0 ; i<numsurfedges ; i++)
  313.         dsurfedges[i] = LittleLong (dsurfedges[i]);
  314.  
  315. //
  316. // edges
  317. //
  318.     for (i=0 ; i<numedges ; i++)
  319.     {
  320.         dedges[i].v[0] = LittleShort (dedges[i].v[0]);
  321.         dedges[i].v[1] = LittleShort (dedges[i].v[1]);
  322.     }
  323. }
  324.  
  325.  
  326. dheader_t    *header;
  327.  
  328. int CopyLump (int lump, void *dest, int size)
  329. {
  330.     int        length, ofs;
  331.  
  332.     length = header->lumps[lump].filelen;
  333.     ofs = header->lumps[lump].fileofs;
  334.     
  335.     if (length % size)
  336.         Error ("LoadBSPFile: odd lump size");
  337.     
  338.     memcpy (dest, (byte *)header + ofs, length);
  339.  
  340.     return length / size;
  341. }
  342.  
  343. /*
  344. =============
  345. LoadBSPFile
  346. =============
  347. */
  348. void    LoadBSPFile (char *filename)
  349. {
  350.     int            i;
  351.     
  352. //
  353. // load the file header
  354. //
  355.     LoadFile (filename, (void **)&header);
  356.  
  357. // swap the header
  358.     for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
  359.         ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
  360.  
  361.     if (header->version != BSPVERSION)
  362.         Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
  363.  
  364.     nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
  365.     numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
  366.     numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
  367.     numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
  368.     numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
  369.     numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
  370.     numclipnodes = CopyLump (LUMP_CLIPNODES, dclipnodes, sizeof(dclipnode_t));
  371.     numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
  372.     nummarksurfaces = CopyLump (LUMP_MARKSURFACES, dmarksurfaces, sizeof(dmarksurfaces[0]));
  373.     numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
  374.     numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
  375.  
  376.     texdatasize = CopyLump (LUMP_TEXTURES, dtexdata, 1);
  377.     visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
  378.     lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
  379.     entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
  380.  
  381.     free (header);        // everything has been copied out
  382.         
  383. //
  384. // swap everything
  385. //    
  386.     SwapBSPFile (false);
  387.  
  388.     dmodels_checksum = FastChecksum( dmodels, nummodels*sizeof(dmodels[0]) );
  389.     dvertexes_checksum = FastChecksum( dvertexes, numvertexes*sizeof(dvertexes[0]) );
  390.     dplanes_checksum = FastChecksum( dplanes, numplanes*sizeof(dplanes[0]) );
  391.     dleafs_checksum = FastChecksum( dleafs, numleafs*sizeof(dleafs[0]) );
  392.     dnodes_checksum = FastChecksum( dnodes, numnodes*sizeof(dnodes[0]) );
  393.     texinfo_checksum = FastChecksum( texinfo, numtexinfo*sizeof(texinfo[0]) );
  394.     dclipnodes_checksum = FastChecksum( dclipnodes, numclipnodes*sizeof(dclipnodes[0]) );
  395.     dfaces_checksum = FastChecksum( dfaces, numfaces*sizeof(dfaces[0]) );
  396.     dmarksurfaces_checksum = FastChecksum( dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0]) );
  397.     dsurfedges_checksum = FastChecksum( dsurfedges, numsurfedges*sizeof(dsurfedges[0]) );
  398.     dedges_checksum = FastChecksum( dedges, numedges*sizeof(dedges[0]) );
  399.     dtexdata_checksum = FastChecksum( dtexdata, numedges*sizeof(dtexdata[0]) );
  400.     dvisdata_checksum = FastChecksum( dvisdata, visdatasize*sizeof(dvisdata[0]) );
  401.     dlightdata_checksum = FastChecksum( dlightdata, lightdatasize*sizeof(dlightdata[0]) );
  402.     dentdata_checksum = FastChecksum( dentdata, entdatasize*sizeof(dentdata[0]) );
  403.  
  404. }
  405.  
  406. //============================================================================
  407.  
  408. FILE        *wadfile;
  409. dheader_t    outheader;
  410.  
  411. void AddLump (int lumpnum, void *data, int len)
  412. {
  413.     lump_t *lump;
  414.  
  415.     lump = &header->lumps[lumpnum];
  416.     
  417.     lump->fileofs = LittleLong( ftell(wadfile) );
  418.     lump->filelen = LittleLong(len);
  419.     SafeWrite (wadfile, data, (len+3)&~3);
  420. }
  421.  
  422. /*
  423. =============
  424. WriteBSPFile
  425.  
  426. Swaps the bsp file in place, so it should not be referenced again
  427. =============
  428. */
  429. void    WriteBSPFile (char *filename)
  430. {        
  431.     header = &outheader;
  432.     memset (header, 0, sizeof(dheader_t));
  433.     
  434.     SwapBSPFile (true);
  435.  
  436.     header->version = LittleLong (BSPVERSION);
  437.     
  438.     wadfile = SafeOpenWrite (filename);
  439.     SafeWrite (wadfile, header, sizeof(dheader_t));    // overwritten later
  440.  
  441.     AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
  442.     AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
  443.     AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
  444.     AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
  445.     AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
  446.     AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
  447.     AddLump (LUMP_CLIPNODES, dclipnodes, numclipnodes*sizeof(dclipnode_t));
  448.     AddLump (LUMP_MARKSURFACES, dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0]));
  449.     AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
  450.     AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
  451.     AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
  452.  
  453.     AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
  454.     AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
  455.     AddLump (LUMP_ENTITIES, dentdata, entdatasize);
  456.     AddLump (LUMP_TEXTURES, dtexdata, texdatasize);
  457.     
  458.     fseek (wadfile, 0, SEEK_SET);
  459.     SafeWrite (wadfile, header, sizeof(dheader_t));
  460.     fclose (wadfile);    
  461. }
  462.  
  463. //============================================================================
  464.  
  465. #define ENTRIES(a)        (sizeof(a)/sizeof(*(a)))
  466. #define ENTRYSIZE(a)    (sizeof(*(a)))
  467.  
  468. ArrayUsage( char *szItem, int items, int maxitems, int itemsize )
  469. {
  470.     float    percentage = maxitems ? items * 100.0 / maxitems : 0.0;
  471.  
  472.     printf("%-12s  %7i/%-7i  %7i/%-7i  (%4.1f%%)", 
  473.            szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage );
  474.     if ( percentage > 80.0 )
  475.         printf( "VERY FULL!\n" );
  476.     else if ( percentage > 95.0 )
  477.         printf( "SIZE DANGER!\n" );
  478.     else if ( percentage > 99.9 )
  479.         printf( "SIZE OVERFLOW!!!\n" );
  480.     else
  481.         printf( "\n" );
  482.     return items * itemsize;
  483. }
  484.  
  485. GlobUsage( char *szItem, int itemstorage, int maxstorage )
  486. {
  487.     float    percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0;
  488.     printf("%-12s     [variable]    %7i/%-7i  (%4.1f%%)", 
  489.            szItem, itemstorage, maxstorage, percentage );
  490.     if ( percentage > 80.0 )
  491.         printf( "VERY FULL!\n" );
  492.     else if ( percentage > 95.0 )
  493.         printf( "SIZE DANGER!\n" );
  494.     else if ( percentage > 99.9 )
  495.         printf( "SIZE OVERFLOW!!!\n" );
  496.     else
  497.         printf( "\n" );
  498.     return itemstorage;
  499. }
  500.  
  501. /*
  502. =============
  503. PrintBSPFileSizes
  504.  
  505. Dumps info about current file
  506. =============
  507. */
  508. void PrintBSPFileSizes (void)
  509. {
  510.     int    numtextures = texdatasize ? ((dmiptexlump_t*)dtexdata)->nummiptex : 0;
  511.     int    totalmemory = 0;
  512.  
  513.     printf("\n");
  514.     printf("Object names  Objects/Maxobjs  Memory / Maxmem  Fullness\n" );
  515.     printf("------------  ---------------  ---------------  --------\n" );
  516.  
  517.     totalmemory += ArrayUsage( "models",        nummodels,        ENTRIES(dmodels),        ENTRYSIZE(dmodels) );
  518.     totalmemory += ArrayUsage( "planes",        numplanes,        ENTRIES(dplanes),        ENTRYSIZE(dplanes) );
  519.     totalmemory += ArrayUsage( "vertexes",        numvertexes,    ENTRIES(dvertexes),        ENTRYSIZE(dvertexes) );
  520.     totalmemory += ArrayUsage( "nodes",            numnodes,        ENTRIES(dnodes),        ENTRYSIZE(dnodes) );
  521.     totalmemory += ArrayUsage( "texinfos",        numtexinfo,        ENTRIES(texinfo),        ENTRYSIZE(texinfo) );
  522.     totalmemory += ArrayUsage( "faces",            numfaces,        ENTRIES(dfaces),        ENTRYSIZE(dfaces) );
  523.     totalmemory += ArrayUsage( "clipnodes",        numclipnodes,    ENTRIES(dclipnodes),    ENTRYSIZE(dclipnodes) );
  524.     totalmemory += ArrayUsage( "leaves",        numleafs,        ENTRIES(dleafs),        ENTRYSIZE(dleafs) );
  525.     totalmemory += ArrayUsage( "marksurfaces",    nummarksurfaces,ENTRIES(dmarksurfaces),    ENTRYSIZE(dmarksurfaces) );
  526.     totalmemory += ArrayUsage( "surfedges",        numsurfedges,    ENTRIES(dsurfedges),    ENTRYSIZE(dsurfedges) );
  527.     totalmemory += ArrayUsage( "edges",            numedges,        ENTRIES(dedges),        ENTRYSIZE(dedges) );
  528.  
  529.     totalmemory += GlobUsage( "texdata",        texdatasize,    sizeof(dtexdata) );
  530.     totalmemory += GlobUsage( "lightdata",        lightdatasize,    sizeof(dlightdata) );
  531.     totalmemory += GlobUsage( "visdata",        visdatasize,    sizeof(dvisdata) );
  532.     totalmemory += GlobUsage( "entdata",        entdatasize,    sizeof(dentdata) );
  533.  
  534.     printf( "=== Total BSP file data space used: %d bytes ===\n", totalmemory );
  535. }
  536.  
  537.  
  538. /*
  539. =================
  540. ParseEpair
  541. =================
  542. */
  543. epair_t *ParseEpair (void)
  544. {
  545.     epair_t    *e;
  546.     
  547.     e = malloc (sizeof(epair_t));
  548.     memset (e, 0, sizeof(epair_t));
  549.     
  550.     if (strlen(token) >= MAX_KEY-1)
  551.         Error ("ParseEpar: token too long");
  552.     e->key = copystring(token);
  553.     GetToken (false);
  554.     if (strlen(token) >= MAX_VALUE-1)
  555.         Error ("ParseEpar: token too long");
  556.     e->value = copystring(token);
  557.  
  558.     return e;
  559. }
  560.  
  561.  
  562. /*
  563. ================
  564. ParseEntity
  565. ================
  566. */
  567. qboolean    ParseEntity (void)
  568. {
  569.     epair_t        *e;
  570.     entity_t    *mapent;
  571.  
  572.     if (!GetToken (true))
  573.         return false;
  574.  
  575.     if (strcmp (token, "{") )
  576.         Error ("ParseEntity: { not found");
  577.     
  578.     if (num_entities == MAX_MAP_ENTITIES)
  579.         Error ("num_entities == MAX_MAP_ENTITIES");
  580.  
  581.     mapent = &entities[num_entities];
  582.     num_entities++;
  583.  
  584.     do
  585.     {
  586.         if (!GetToken (true))
  587.             Error ("ParseEntity: EOF without closing brace");
  588.         if (!strcmp (token, "}") )
  589.             break;
  590.         e = ParseEpair ();
  591.         e->next = mapent->epairs;
  592.         mapent->epairs = e;
  593.     } while (1);
  594.     
  595.     return true;
  596. }
  597.  
  598. /*
  599. ================
  600. ParseEntities
  601.  
  602. Parses the dentdata string into entities
  603. ================
  604. */
  605. void ParseEntities (void)
  606. {
  607.     num_entities = 0;
  608.     ParseFromMemory (dentdata, entdatasize);
  609.  
  610.     while (ParseEntity ())
  611.     {
  612.     }    
  613. }
  614.  
  615.  
  616. /*
  617. ================
  618. UnparseEntities
  619.  
  620. Generates the dentdata string from all the entities
  621. ================
  622. */
  623. void UnparseEntities (void)
  624. {
  625.     char    *buf, *end;
  626.     epair_t    *ep;
  627.     char    line[2048];
  628.     int        i;
  629.     
  630.     buf = dentdata;
  631.     end = buf;
  632.     *end = 0;
  633.     
  634.     for (i=0 ; i<num_entities ; i++)
  635.     {
  636.         ep = entities[i].epairs;
  637.         if (!ep)
  638.             continue;    // ent got removed
  639.         
  640.         strcat (end,"{\n");
  641.         end += 2;
  642.                 
  643.         for (ep = entities[i].epairs ; ep ; ep=ep->next)
  644.         {
  645.             sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
  646.             strcat (end, line);
  647.             end += strlen(line);
  648.         }
  649.         strcat (end,"}\n");
  650.         end += 2;
  651.  
  652.         if (end > buf + MAX_MAP_ENTSTRING)
  653.             Error ("Entity text too long");
  654.     }
  655.     entdatasize = end - buf + 1;
  656. }
  657.  
  658.  
  659.  
  660. void     SetKeyValue (entity_t *ent, char *key, char *value)
  661. {
  662.     epair_t    *ep;
  663.     
  664.     for (ep=ent->epairs ; ep ; ep=ep->next)
  665.         if (!strcmp (ep->key, key) )
  666.         {
  667.             free (ep->value);
  668.             ep->value = copystring(value);
  669.             return;
  670.         }
  671.     ep = malloc (sizeof(*ep));
  672.     ep->next = ent->epairs;
  673.     ent->epairs = ep;
  674.     ep->key = copystring(key);
  675.     ep->value = copystring(value);
  676. }
  677.  
  678. char     *ValueForKey (entity_t *ent, char *key)
  679. {
  680.     epair_t    *ep;
  681.     
  682.     for (ep=ent->epairs ; ep ; ep=ep->next)
  683.         if (!strcmp (ep->key, key) )
  684.             return ep->value;
  685.     return "";
  686. }
  687.  
  688. vec_t    FloatForKey (entity_t *ent, char *key)
  689. {
  690.     char    *k;
  691.     
  692.     k = ValueForKey (ent, key);
  693.     return atof(k);
  694. }
  695.  
  696. void     GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
  697. {
  698.     char    *k;
  699.     double    v1, v2, v3;
  700.  
  701.     k = ValueForKey (ent, key);
  702. // scanf into doubles, then assign, so it is vec_t size independent
  703.     v1 = v2 = v3 = 0;
  704.     sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
  705.     vec[0] = v1;
  706.     vec[1] = v2;
  707.     vec[2] = v3;
  708. }
  709.  
  710.